package com.weblog.user.service;

import com.weblog.model.user.Admin;
import com.weblog.model.user.Role;
import com.weblog.user.dao.AdminDao;
import com.weblog.user.dao.RoleDao;
import com.weblog.user.dao.UserDao;
import com.weblog.user.entity.AdminInfoDTO;
import com.weblog.user.utils.AccessUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import util.IdWorker;
import util.MapSizeUtil;

import javax.persistence.criteria.*;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class AdminService {

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private AdminDao adminDao;

    @Autowired
    private BCryptPasswordEncoder encoder;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private AccessUtil accessUtil;

    @Autowired
    private MapSizeUtil mapSizeUtil;


    public void addAdmin(Admin admin) {
        admin.setId(idWorker.nextId() + "");
        //密码加密
        admin.setPassword(encoder.encode(admin.getPassword()));
        adminDao.save(admin);
    }

    /**
     * 登录
     *
     * @param admin
     * @return
     */
    public AdminInfoDTO login(Admin admin) {
        Admin login_admin = adminDao.findByUsername(admin.getUsername());

        if (login_admin != null && encoder.matches(admin.getPassword(), login_admin.getPassword())) {
            Admin admin1 = adminDao.findById(login_admin.getId()).get();
            AdminInfoDTO dto=new AdminInfoDTO();
            dto.setAdmin(admin1);
            Set<Role> roles = admin1.getRoles();
            List<Role> roles_list = new ArrayList<>(roles);
            dto.setRoles(roles_list);
            return dto;
        }
        return null;
    }

    /**
     * 分页多条件查询
     *
     * @param searchMap
     * @param page
     * @param size
     * @return
     */
    public Page<Admin> PageBySearch(Map<String, Object> searchMap, int page, int size) {
        Specification<Admin> specification = createSpecification(searchMap);
        Pageable pageable = PageRequest.of(page - 1, size);
        return adminDao.findAll(specification, pageable);
    }

    /**
     * 构建构建查询
     *
     * @param searchMap
     * @return
     */
    private Specification<Admin> createSpecification(Map<String, Object> searchMap) {

        return new Specification<Admin>() {

            /**
             * @param root  根对象，也就是要把条件封装到哪个对象中，where leiming=user.getId
             * @param query 封装的是查询关键字， 比如group by order by等
             * @param cb    用来封装条件对象
             * @return
             */
            @Override
            public Predicate toPredicate(Root<Admin> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<Predicate>();


                // 姓名
                if (searchMap.get("name") != null && !"".equals(searchMap.get("name"))) {
                    list.add(cb.like(root.get("name").as(String.class), "%" + (String) searchMap.get("name") + "%"));
                }

                // 管理员状态 1是 0否
                if (searchMap.get("state") != null && !"".equals(searchMap.get("state"))) {
                    Expression<String> state = root.get("state").as(String.class);
                    String search_state = (String) searchMap.get("state");
                    //约定 0代表查询所有用户，忽略黑名单状态
                    if (!"2".equals(search_state)) {
                        Predicate predicate = cb.equal(state, search_state);
                        list.add(predicate);
                    }
                }
                if (searchMap.get("currentUserId") != null && !"".equals(searchMap.get("currentUserId"))) {
                    //排除掉当前用户信息
                    list.add(cb.notEqual(root.get("id").as(String.class), (String) searchMap.get("currentUserId")));
                }

                //new一个Predicaet数组存放最终返回值的条件
                Predicate[] predicates = new Predicate[list.size()];
                //list转成数组
                predicates = list.toArray(predicates);
                return cb.and(predicates);
            }
        };

    }


    /**
     * 拉黑
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public int blackAdmin(String id) {
        String token = (String) request.getAttribute("claims_superAadmin");
        if (token == null || "".equals(token)) {
            //普通管理员
            return 2;//权限不足

        }
        //超级管理员
        int flag = adminDao.blackAdminById(id);
        if (flag > 0) {
            //删除成功
            return 1;
        } else {
            //删除失败
            return 0;
        }

    }

    /**
     * 根据ID查询管理员信息
     *
     * @param id
     * @return
     */
    public Admin findById(String id) {
        if (id != null) {
            return adminDao.findById(id).get();
        }
        return null;

    }


    /**
     * 增加
     *
     * @param admin
     */
    @Transactional(rollbackFor = Exception.class)
    public int add(Admin admin) {
        Admin username_admin = adminDao.findByUsername(admin.getUsername());
        if (username_admin == null) {
            String token = (String) request.getAttribute("claims_superAadmin");
            if (token == null || "".equals(token)) {
                //普通管理员
                int flag = accessUtil.isAccess("role_user", "user_add");
                if (flag == 2) {
                    return 2;
                }

                adminDao.save(admin);
                //添加默认角色
                adminDao.findById(admin.getId()).get().getRoles().add(roleDao.findRoleByRname("role_admin_common"));
                return 1;
            }

            adminDao.save(admin);
            //添加默认角色
            adminDao.findById(admin.getId()).get().getRoles().add(roleDao.findRoleByRname("role_admin_common"));
            return 1;
        }
        //登录名已存在
        return 3;
    }

    /**
     * 修改
     *
     * @param admin
     */
    @Transactional(rollbackFor = Exception.class)
    public int update(Admin admin) {
        Admin username = adminDao.findAllByUsernameAndIdNot(admin.getUsername(), admin.getId());
        if (username == null || "".equals(username)) {
            String token = (String) request.getAttribute("claims_superAadmin");
            String stateOld = adminDao.findStateById(admin.getId());

            if (token == null || "".equals(token)) {
                //普通管理员
                if(!stateOld.equals(admin.getState())){
                    //修改了状态
                    return 4;
                }else {
                    int flag = accessUtil.isAccess("role_user", "user_update");
                    if (flag == 2) {
                        return 2;
                    }
                    admin.setLastlogin(new Date());
                    adminDao.save(admin);
                    return 1;
                }

            }
            //超级管理员
            admin.setLastlogin(new Date());
            adminDao.save(admin);
            return 1;
        }
        //用户名存在
        return 3;

    }

    /**
     * 给管理员分配角色
     *
     * @param id
     * @param rid
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int addRoleToAdmin(String id, String rid) {
        Admin admin = null;
        Set<Role> roles = null;
        String token = (String) request.getAttribute("claims_superAadmin");
        if (token == null || "".equals(token)) {
            //普通管理员
            if ("1".equals(adminDao.findById(id).get().getIssuper())) {
                //操作对象是超级管理员
                return 2;
            }
            if ("role_superadmin".equals(roleDao.findById(rid).get().getRname())) {
                //分配的角色是超级管理员
                return 2;
            }
            int flag = accessUtil.isAccess("role_user", "user_update");
            if (flag == 2) {
                //权限不足
                return flag;
            }
            admin = adminDao.findById(id).get();
            roles = admin.getRoles();
            for (Role r : roles) {
                if (rid.equals(r.getRid())) {
                    //该用户已拥有此角色，重复分配
                    return 3;
                }
            }
            roles.add(roleDao.findById(rid).get());
            return 1;
        }
        //超级管理员
        if ("role_superadmin".equals(roleDao.findById(rid).get().getRname())) {
            //分配的角色是超级管理员
            return 4;
        }
        admin = adminDao.findById(id).get();
        roles = admin.getRoles();
        for (Role r : roles) {
            if (rid.equals(r.getRid())) {
                //该用户已拥有此角色，重复分配
                return 3;
            }
        }
        roles.add(roleDao.findById(rid).get());
        return 1;
    }

    /**
     * 根据管理员id查询角色列表
     *
     * @param id
     * @return
     */
    public List<Role> queryRoleListByAdminid(String id) {
        Admin admin = adminDao.findById(id).get();
        Set<Role> roles = admin.getRoles();
        List<Role> roleList = new ArrayList<>(roles);
        return roleList;
    }

    /**
     * 根据管理员id删除角色关系
     *
     * @param id
     * @param rid
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteRoleOfAdmin(String id, String rid) {
        Role target_role = roleDao.findById(rid).get();
        if ("role_admin_common".equals(target_role.getRname())) {
            //基础角色不允许删除
            return 0;
        }
        String token = (String) request.getAttribute("claims_superAadmin");
        if (token == null || "".equals(token)) {
            //普通管理员
            if ("1".equals(adminDao.findById(id).get().getIssuper())) {
                //目标用户为超级管理员，权限不足
                return 2;
            }
            int flag = accessUtil.isAccess("role_user", "user_update");
            if (flag == 2) {
                //权限不足
                return 2;
            }
            Admin admin = adminDao.findById(id).get();
            Set<Role> roles = admin.getRoles();
            roles.remove(target_role);
            return 1;
        }
        //超级管理员
        Admin admin = adminDao.findById(id).get();
        Set<Role> roles = admin.getRoles();
        roles.remove(target_role);
        return 1;
    }


}
